import axios from 'axios'
import qs from 'qs'
import dayjs from 'dayjs'
import { respUtil } from '@/utils/response'
import * as FileSaver from 'file-saver'

// axios 实例
const instance = axios.create({
  timeout: 180000,
  responseType: 'json',
  paramsSerializer: function (params) {
    return qs.stringify(params, {
      arrayFormat: 'indices',
      serializeDate: date => {
        return dayjs(date).format('yyyy-MM-dd HH:mm:ss')
      }
    })
  }
})

// 添加请求拦截器
instance.interceptors.request.use(
  request => {
    // if (request.params) {
    //   /**
    //    * axios会对get请求的整个url进行encodeURI，导致有些get方法不能传[]，
    //    * 所以在此拦截器中抢先进行encodeURIComponent处理，避开axios的encodeURI
    //    * qs.stringify(config.params, {indices: false}) 等方法都不好用,不利于后台参数接收
    //    */
    //   let url = `${request.url}?`
    //   const keys = Object.keys(request.params)
    //   for (const key of keys) {
    //     let val = request.params[key]
    //     if (typeof val === 'object') {
    //       val = JSON.stringify(val)
    //     }
    //     url += `${key}=${encodeURIComponent(val)}&`
    //   }
    //   request.url = url.substring(0, url.length - 1)
    //   request.params = {}
    // }
    return request
  },
  error => {
    return Promise.reject(error)
  }
)

// 添加响应拦截器
instance.interceptors.response.use(
  response => {
    if (response.data instanceof Blob && response.config.params && response.config.params.export) {
      // 只处理getPage的导出请求
      FileSaver.saveAs(response.data, respUtil.getFileName(response))
      return { status: 200, data: { success: true, skipResolve: true } } //todo 伪装失败, 避免调用端callback处理异常
    } else {
      return response
    }
  },
  async error => {
    const response = error.response
    // 超时重新请求
    const config = error.config
    // 全局的请求次数,请求的间隙
    const [RETRY_COUNT, RETRY_DELAY] = [0, 1000]

    if (config && RETRY_COUNT) {
      // 设置用于跟踪重试计数的变量
      config.__retryCount = config.__retryCount || 3
      // 检查是否已经把重试的总数用完
      if (config.__retryCount >= RETRY_COUNT) {
        return Promise.reject(response || { message: error.message })
      }
      // 增加重试计数
      config.__retryCount++
      // 创造新的Promise来处理指数后退
      const backOff = new Promise<void>(resolve => {
        setTimeout(() => {
          resolve()
        }, RETRY_DELAY || 1)
      })

      // instance重试请求的Promise
      return backOff.then(() => {
        return instance(config)
      })
    }
    return Promise.reject(response || { message: error.message })
  }
)

export default instance
